Dependency Injection Architecture Diagrams
Current Architecture (Before DI)
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β main() β
β (toolkit.go) β
βββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
β
β Creates App struct
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β App Struct β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Fields: β
β - menu: *Menu (created in main) β
β - reader: *RegistryReader (created in App.init()) β
β - config: *AppConfig (created in main) β
β - outputDir, logsDir, evidenceDir, reportsDir, exeDir β
β β
β Methods: β
β - init() - Creates reader, sets global logger β
β - executeReport() - Creates HTMLReport & EvidenceLogger β
β - executeReportQuiet() - Duplicate of executeReport() β
β - runReports(), viewHTMLReports(), etc. β
βββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
β executeReport() calls
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Direct Dependencies β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β pkg.LoadConfig(configPath) β
β β β
β pkg.NewHTMLReport(reportName, outputDir) β
β β β
β htmlReport.SetRegistryReader(app.reader) β TIGHT COUPLING β
β β β
β pkg.NewEvidenceLogger(evidenceDir, reportType) β
β β β
β evidenceLogger.GatherMachineInfo(app.reader) β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β οΈ PROBLEMS β οΈ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 1. Global State: slog.SetDefault(logger) in init() β
β β Cannot run tests in parallel β
β β Hidden dependency on global logger β
β β
β 2. Direct Instantiation: Components create their own deps β
β β Hard to mock for testing β
β β Tight coupling between layers β
β β
β 3. No Interfaces: All concrete types β
β β Cannot swap implementations β
β β Violates Dependency Inversion Principle β
β β
β 4. Mixed Concerns: App does initialization + business logic β
β β Single Responsibility Principle violated β
β β Hard to test business logic in isolation β
β β
β 5. Code Duplication: executeReport() vs executeReportQuiet() β
β β Maintenance nightmare β
β β Bug fixes must be applied twice β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Target Architecture (After DI)
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β main() β
β (toolkit.go) β
ββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
β 1. Parse flags & create AppConfig
β 2. Setup logger (NO global state)
β 3. Create directories
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β NewDependencies(config, logger) β
β (dependencies.go) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Returns Dependencies struct containing: β
β β
β β’ Logger: *slog.Logger β
β β’ Config: *AppConfig β
β β’ RegistryService: pkg.RegistryService (interface) β
β β’ UIService: pkg.UIService (interface) β
β β’ ConfigService: pkg.ConfigService (interface) β
β β’ FileService: pkg.FileService (interface) β
β β
β Methods: β
β β’ Validate() - Ensures all deps are non-nil β
β β’ Clone(config) - Creates copy for testing β
βββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
β Dependencies passed to
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β NewApp(deps) β
β (toolkit.go) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β App Struct: β
β - deps: *Dependencies β
β - factory: *ServiceFactory β
β β
β Methods (Business Logic Only): β
β - runInteractive() - Interactive menu loop β
β - runReports() - Uses deps.UIService, factory β
β - viewHTMLReports() - Uses deps.FileService β
β - listReportsCLI() - Uses deps.FileService β
β - runReportCLI() - Uses ReportRunner β
β β
β β
NO initialization logic β
β β
NO direct component creation β
β β
All dependencies injected β
βββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
β Uses factory to create services
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ServiceFactory (factory.go) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β CreateReportService(title, outputDir) β ReportService β
β Returns: pkg.NewHTMLReport(title, outputDir, logger, reg) β
β β
β CreateEvidenceService(dir, type) β EvidenceService β
β Returns: pkg.NewEvidenceLogger(dir, type, logger) β
β β
β CreateReportRunner() β *ReportRunner β
β Returns: NewReportRunner(deps) β
βββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
β Factory creates
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ReportRunner Service β
β (report_runner.go) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Constructor: β
β NewReportRunner(deps *Dependencies) *ReportRunner β
β β
β Methods: β
β ExecuteReport(configFile, quiet) error β
β 1. Uses deps.ConfigService.LoadConfig() β
β 2. Uses factory.CreateReportService() β
β 3. Uses factory.CreateEvidenceService() β
β 4. Uses deps.RegistryService for queries β
β 5. Generates report and evidence β
β β
β β
Single responsibility: Execute reports β
β β
Testable with mocks β
β β
No code duplication β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Interface Layer
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β pkg/interfaces.go β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β interface RegistryService { β
β ReadString(...) β
β ReadInteger(...) β
β ReadBinary(...) β
β ReadStrings(...) β
β ReadValue(...) β
β BatchRead(...) β
β } β
β β
β interface ReportService { β
β Generate() error β
β AddResult(...) β
β AddResultWithDetails(...) β
β SetMetadata(...) β
β GetOutputPath() string β
β } β
β β
β interface EvidenceService { β
β GatherMachineInfo(RegistryService) error β
β LogResult(...) β
β Finalize() error β
β GetSummaryText() string β
β GetLogPath() string β
β } β
β β
β interface UIService { β
β ShowHeader() β
β ShowMainMenu() int β
β ShowReportMenuDynamic(...) int β
β ShowError(string) β
β ShowSuccess(string) β
β Pause() β
β GetIntInput() int β
β // ... β
β } β
β β
β interface ConfigService { β
β LoadConfig(path) (*Config, error) β
β ParseRootKey(string) (registry.Key, error) β
β } β
β β
β interface FileService { β
β FindReportsDirectory(exeDir) string β
β ResolveDirectory(dir, exeDir) string β
β ListReports(reportsDir) ([]ReportInfo, error) β
β OpenBrowser(url) error β
β OpenFile(path) error β
β } β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
β Implemented by
β
βββββββββββββββ΄ββββββββββββββ
β β
βΌ βΌ
βββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββ
β Production Implementationsβ β Mock Implementations β
βββββββββββββββββββββββββββββ€ βββββββββββββββββββββββββββββ€
β β β β
β RegistryReader β β MockRegistryService β
β HTMLReport β β MockReportService β
β EvidenceLogger β β MockEvidenceService β
β Menu β β MockUIService β
β ConfigServiceImpl β β MockConfigService β
β FileServiceImpl β β MockFileService β
β β β β
β Used in production β β Used in unit tests β
βββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββ
Dependency Flow Diagram
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Application Layers β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Layer 1: Entry Point
ββ main() (toolkit.go)
β ββ Responsibilities:
β β’ Parse CLI flags
β β’ Create configuration
β β’ Setup logger
β β’ Wire dependencies
β β’ Start application
Layer 2: Dependency Container
ββ Dependencies (dependencies.go)
β ββ Contains:
β β’ Logger (*slog.Logger)
β β’ Config (*AppConfig)
β β’ All service interfaces
β ββ Methods:
β β’ Validate() - Ensure all deps set
β β’ Clone() - For testing
Layer 3: Application Core
ββ App (toolkit.go)
β ββ Responsibilities:
β β’ Interactive menu handling
β β’ CLI command routing
β β’ User interaction coordination
β ββ Dependencies:
β β’ deps *Dependencies
β β’ factory *ServiceFactory
Layer 4: Service Layer
ββ ServiceFactory (factory.go)
β ββ Creates:
β β’ ReportService instances
β β’ EvidenceService instances
β β’ ReportRunner instances
β
ββ ReportRunner (report_runner.go)
β ββ Responsibilities:
β β’ Execute compliance reports
β β’ Coordinate services
β β’ Handle errors
β ββ Dependencies:
β β’ deps *Dependencies
β β’ factory *ServiceFactory
Layer 5: Business Logic (pkg/)
ββ Services (implement interfaces)
β ββ RegistryReader - Registry operations
β ββ HTMLReport - Report generation
β ββ EvidenceLogger - Audit logging
β ββ Menu - User interface
β ββ ConfigService - Configuration loading
β ββ FileService - File operations
β
ββ Domain Models
ββ Config, Query, ReportMetadata
ββ ReportData, SystemInfo, QueryResult
ββ ComplianceEvidence, ScanResult
Layer 6: Infrastructure
ββ External Dependencies
ββ golang.org/x/sys/windows/registry
ββ html/template
ββ log/slog
ββ Standard library
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Dependency Direction β
β β
β Higher layers depend on lower layers β
β All layers depend on interfaces (Layer 5 interfaces) β
β Lower layers have NO knowledge of higher layers β
β Follows Clean Architecture principles β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Testing Strategy Diagram
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Testing Pyramid β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β²
β± β²
β± β²
β± β²
β± β²
β± E2E β²
β± Tests β²
β±ββββββββββββββ²
β± β²
β± Integration β²
β± Tests β²
β±ββββββββββββββββββββββ²
β± β²
β± Unit Tests β²
β± (with mocks) β²
β±ββββββββββββββββββββββββββββββ²
β±_______________________________β²
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Unit Tests (70% of tests) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Test: ReportRunner.ExecuteReport() β
β Mocks: MockRegistryService, MockConfigService, β
β MockReportService, MockEvidenceService β
β Assertion: Correct methods called with correct params β
β β
β Test: HTMLReport.Generate() β
β Mocks: MockRegistryService β
β Assertion: HTML output matches expected template β
β β
β Test: Dependencies.Validate() β
β Mocks: None (pure logic) β
β Assertion: Returns error when deps missing β
β β
β β
Fast execution (milliseconds) β
β β
No external dependencies β
β β
High code coverage (target: 75%+) β
β β
Isolated failure detection β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Integration Tests (20% of tests) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Test: ReportRunner with Real RegistryReader β
β Real: RegistryReader, FileSystem β
β Mocks: None β
β Assertion: Report generated with real registry data β
β β
β Test: Full Report Generation Flow β
β Real: All services β
β Mocks: None β
β Assertion: HTML + Evidence files created correctly β
β β
β β οΈ Requires Windows environment β
β β οΈ Slower execution (seconds) β
β β
Tests real interactions β
β β
Catches integration issues β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β End-to-End Tests (10% of tests) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Test: CLI - List Reports β
β Command: ./ComplianceToolkit.exe -list β
β Assertion: All reports listed, exit code 0 β
β β
β Test: CLI - Run Single Report β
β Command: ./ComplianceToolkit.exe -report=NIST_800_171.json β
β Assertion: HTML generated, evidence logged, exit code 0 β
β β
β Test: Interactive Mode - Run All Reports β
β Input: Simulated user input (1 β all reports β 0) β
β Assertion: All reports completed, files created β
β β
β β οΈ Requires Windows + admin privileges β
β β οΈ Slowest execution (minutes) β
β β
Tests complete user workflows β
β β
Smoke tests for releases β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Before/After Comparison
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β BEFORE (Current State) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β main() β
β ββ app := &App{...} β
β ββ app.init() β
β ββ slog.SetDefault(logger) β GLOBAL STATE β
β ββ app.reader = pkg.NewRegistryReader(...) β
β β
β app.executeReport() β
β ββ htmlReport := pkg.NewHTMLReport(...) β
β ββ htmlReport.SetRegistryReader(app.reader) β SETTER β
β ββ evidence := pkg.NewEvidenceLogger(...) β
β ββ evidence.GatherMachineInfo(app.reader) β
β β
β Testing: β
β β Cannot mock RegistryReader β
β β Cannot test executeReport() in isolation β
β β Tests interfere with each other (global logger) β
β β No interfaces to implement β
β β
β Metrics: β
β β’ Test Coverage: 15% β
β β’ Cyclomatic Complexity: 45 β
β β’ Coupling: High β
β β’ Testability: Low β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β¬οΈ REFACTORING β¬οΈ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β AFTER (Target State) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β main() β
β ββ logger := setupLogger(...) β
LOCAL SCOPE β
β ββ deps := NewDependencies(config, logger) β
β ββ app, err := NewApp(deps) β
CONSTRUCTOR INJECTION β
β ββ app.runInteractive() β
β β
β ReportRunner.ExecuteReport() β
β ββ reportSvc := factory.CreateReportService(...) β
β ββ evidenceSvc := factory.CreateEvidenceService(...) β
β ββ evidenceSvc.GatherMachineInfo(deps.RegistryService) β
β ββ reportSvc.Generate() β
β β
β Testing: β
β β
Mock all interfaces easily β
β β
Test any component in isolation β
β β
Parallel test execution β
β β
6 interfaces implemented β
β β
β Metrics: β
β β’ Test Coverage: 75% β
β β’ Cyclomatic Complexity: 25 β
β β’ Coupling: Low β
β β’ Testability: High β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Migration Path
Week 1: Interfaces & Mocks
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 1. Create pkg/interfaces.go β
β 2. Create pkg/mocks/ directory β
β 3. Write MockRegistryService, MockReportService, etc. β
β 4. Write interface compliance tests β
β 5. Verify existing code matches interfaces β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β¬οΈ
Week 2: Services
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 1. Create pkg/config_service.go β
β 2. Create pkg/file_service.go β
β 3. Update pkg/htmlreport.go constructor β
β 4. Update pkg/evidence.go constructor β
β 5. Remove SetRegistryReader() method β
β 6. Write unit tests for all services β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β¬οΈ
Week 3: Dependency Container
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 1. Create cmd/dependencies.go β
β 2. Create cmd/factory.go β
β 3. Update cmd/toolkit.go main() β
β 4. Remove global logger (slog.SetDefault) β
β 5. Update App struct β
β 6. Test with real dependencies β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β¬οΈ
Week 4: Report Runner
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 1. Refactor cmd/report_runner.go β
β 2. Extract helper functions β
β 3. Remove executeReportQuiet() duplication β
β 4. Write comprehensive unit tests β
β 5. Integration tests with mocks β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β¬οΈ
Week 5: Integration
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 1. Update all App methods β
β 2. Remove old initialization code β
β 3. Integration testing (Windows) β
β 4. Regression testing (all reports) β
β 5. Performance benchmarking β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β¬οΈ
Week 6: Polish & Documentation
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 1. Update CLAUDE.md β
β 2. Update ARCHITECTURE.md β
β 3. Add testing guide β
β 4. Code review & final adjustments β
β 5. Merge to main branch β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Success Criteria
β
All interfaces defined and documented
β
All services implement interfaces correctly
β
Zero global state (no slog.SetDefault())
β
Dependencies container validates all deps
β
Factory creates all service instances
β
Unit test coverage β₯ 75%
β
All existing reports still work
β
No performance regression (within 5%)
β
Code complexity reduced (cyclomatic < 30)
β
Documentation updated
β
Rollback plan tested
β
Team trained on new architecture